大小

  C++基本类型的某些方面是由实现确定的,例如int的大小(C.2节)。我总要指出这种依赖性,并常常提出应该避免它们,或者通过某些方式尽可能减小其影响的建议。为什么需要为这些东西操心呢?在各种各样的系统中或使用多种编译器去编程序的人们很注意这些事情,因为如果他们不这样做,那他们就会被迫去花时间寻找和纠正很隐蔽的错误。那些自称不关心移植性的人也确实常常像自己所说的那样去做,因为他们只使用一种系统,并认为自己能承担如下看法:“这个语言不过就是我的编译器所实现的那种东西”。但是,这实际上是一种狭隘的短视的观点。如果你的程序是成功的,那么它就很可能需要移植,而这时某些人就必须去寻找并纠正那些依赖于实现的特征了。此外,程序经常需要为了同一个系统而用其他编译器来编译,甚至你最喜爱的编译器的未来版本在做某些事情时,也可能采用与目前的版本不同的方式。在写程序时,理解程序对实现的依赖性的影响并予以限制,比以后再去踩这个泥潭要容易得多。

  限制依赖于实现的预言特征的影响并不太难,限制依赖于系统的库功能的影响就困难得多了。在所有可能之处都使用标准库的功能是一个办法。

  提供了多种整数类型、多种无符号类型、多种浮点类型的原因就是希望使程序员能够利用各种硬件特性。在许多机器上,不同种类的基础类型之间,在对存储的需求、存储访问时间和计算速度方面存在着明显的差异。如果你了解一台机器,那么就很容易做出选择,例如,选择对某个变量所适用的整数类型。而写出真正可移植性的低级代码就要困难得多。

  C++对象的大小是用char的大小的倍数表示的,所以,按照定义char的大小为1。一个对象或者类型的大小可以用sizeof运算符得到(6.2节)。下面是基本类型的大小所能够保证的性质:

1 = sizeof(char) ⩽ sizeof(short) ⩽ sizeof(int) ⩽ sizeof(long)
1 ⩽ sizeof(bool) ⩽ sizeof(long)
sizeof(char) ⩽ sizeof(wchar_t) ⩽ sizeof(long)
sizeof(float) ⩽ sizeof(double) ⩽ sizeof(long double)
sizeof(N) = sizeof(signed N) = sizeof(unsigned N)

其中的N可以是char、short int、int或long int。此外,这里还保证char至少有8位,short至少有16位,而long至少有32位。一个char能保存机器的字符集中的一个字符。

按照同样的尺度(一个字节0.2 in, 1 in = 0.0254m),一兆字节的存储器将向右延展大约3mile(5km, 1 mile = 1 609.344 m)。

  char类型被假定是由实现选择的,在给定的计算机上选定最适合存储和操作字符的类型,典型情况下就是8位的字节。类似地,int类型也被假定是由实现选择的,采用在给定计算机上最适合存储和操作整数的类型,典型情况下是一个4字节(32位)的机器字。假定得更多就不明智了,因为确实存在着某些采用32字符的机器。

  如果需要的话,有关某个具体实现的所有依赖于实现的特征都可以在< limits>里找到(22.2节)。例如,

    #include <limits>
    #include <iostream>
    int main()
    {
        cout << "largest float == " << numeric_limits<float>::max()
            << ", char is signed == " << numeric_limits<char>::is_signed << '\n';
    }

在赋值和表达式里,都可以随意地混合使用各种基本类型。只要可能,有关的值将会被转换,尽可能不损失信息(C.6节)。

  如果一个值v可以在一个类型T的变量里确切地表示,那么从v到T的转换将是保值的,不会有任何问题。在那些转换不能保值的地方最好是避免有关的转换(C.6.2.6节)。

  你需要在某种细节程度上理解隐式转换,以便能完成重要的项目,特别是去理解别人写的实际代码。当然,这种理解对于阅读下面的各章并不是必需的。

🔚